home *** CD-ROM | disk | FTP | other *** search
- PAGE 60,132
- TITLE MAIN -- SAMPLE ASSEMBLER ROUTINE TO ADD 3 NUMBERS (ADDOUT.ASM)
- COMMENT * Written by Larry Jordan, 1983 *
-
- .RADIX 16 ;DEFAULT NUMBERS ARE HEX
-
- SUBTTL DEFINITIONS OF MACROS
- PAGE
- SCROLL MACRO
- MOV AX,600H ;AH=6 Requests scroll, AL=0 means entire wind
- BIOSCALL ;Invoke BIOS to scroll the window
- ENDM
- ;
- KEYBOARD MACRO
- MOV AH,10D ;Function selected = read keyboard
- DOSCALL ;Invoke DOS to read keyboard
- ENDM
- ;
- LOCATE MACRO
- MOV AH,2 ;Function selected = locate
- BIOSCALL ;Invoke BIOS to move cursor
- ENDM
- PAGE
- DISPLAY MACRO TEXT
- MOV DX,OFFSET TEXT ;Point to message to print
- MOV AH,9 ;Function selected = console output
- DOSCALL ;Invoke DOS to display message
- ENDM
- ;
- DOSCALL MACRO
- INT 21H ;Request DOS service, id in AH
- ENDM
- ;
- BIOSCALL MACRO
- INT 10H ;Request BIOS service, id in AH
- ENDM
-
-
- SUBTTL DESCRIPTION OF THE STACK SEGMENT
- PAGE
- STACKSEG SEGMENT PARA STACK 'STACK'
-
- ; Initial contents of the stack area may be anything. Use of the
- ; word 'STACK ' here does show up nicely when using DEBUG to look
- ; at memory. By setting the stack to some known original value, it
- ; is possible to look at the stack area using DEBUG after the run to
- ; see just how much of the area was actually used.
-
- DW 100 DUP(?)
- STACKSEG ENDS
-
-
- SUBTTL DESCRIPTION OF THE DATA WORKAREA
- PAGE
- DATASEG SEGMENT PARA PUBLIC 'DATA'
-
- FIRST_NUM DW 1,2,3
- STORE_AL DB 0
- STORE_AH DB 0
- STORE_AX DW 0
- LOW_NIBBLE_AL DB 0
- HI_NIBBLE_AL DB 0
- LOW_NIBBLE_AH DB 0
- HI_NIBBLE_AH DB 0
- REPORT_1 DB 'The '
- VARIABLE_1 DW 0
- DB ' total is = '
- VARIABLE_2 DB 0
- VARIABLE_3 DB 0
- VARIABLE_4 DB 0
- VARIABLE_5 DB 0
- DB ' H.',0AH,0DH
- DATASEG ENDS
-
-
- SUBTTL ESTABLISH DOS INTERFACES
- PAGE
-
- CODESEG SEGMENT PARA PUBLIC 'CODE' ;SET UP CODE SEGMENT
-
- MAIN PROC FAR ;SET UP 2 WORD STACK PUSH/POP
-
- ASSUME CS:CODESEG,DS:DATASEG,ES:NOTHING ;GIVE SEGMENTS NAMES
-
- TOTAL_NUM EQU 03 ;TOTAL NUMBER TO BE ADDED EQUAL 10
- EFFZERO EQU 0F0
- ZEROEFF EQU 0F
-
- ;
- ; At entry:
- ; CS=Addr of entry point
- ; IP=0, offset to entry point
- ; SS=Segment address of stack segment
- ; SP=200H, offset into stack of top of stack
- ; DS=Segment address of Program Segment Prefix area
- ; ES=Same as DS
- ;
- ; At exit:
- ; It is the user's responsibility to ensure that:
- ; CS=Segment address of Program Segment Prefix area,
- ; originally in DS or ES.
- ; SS=Same value as at entry
- ; (Other regs may be destroyed.)
-
- SUBTTL ESTABLISH ENTRY LINKAGE FROM DOS
- PAGE
- ; Set up the stack to contain the proper values so this
- ; program can return to DOS.
- ;
- PUSH DS ;Set DOS return segment addr to stack
- SUB AX,AX ;Clear a reg
- PUSH AX ;Put zero return addr to stack
- ;
- ; Establish addressability for the data segment.
- ;
- GO: MOV AX,DATASEG ;Get location of DATA workarea
- MOV DS,AX ;Set segreg base of data workarea
- ;
- ; (Extra Segment, ES segreg, not used)
- ;
- XOR SI,SI ;CLEAR THE SOURCE INDEX
- MOV CX,TOTAL_NUM ;INITILIZE LOOP COUNT
- XOR AX,AX ;CLEAR ACCUMULATOR REGISTER
- ;
- ; Do the addition of 10 numbers
- ;
- LOOP: ADD AX,FIRST_NUM[SI] ;ADD NUMBER IN ADDRESS FIRST_NUM
- ;+ THE CONTENTS OF SI TO SUM
- ADD SI,02 ;INC INDEX BY 2 BYTES (WORD)
- DEC CX ;DECREMENT THE LOOP COUNT REGISTER
- JNZ LOOP ;CONTINUE LOOP IF CX NOT EQU 0
- MOV WORD PTR [STORE_AX],AX ;MOVE ACCUMULATOR TO STORAGE
-
- SUBTTL CLEAR THE SCREEN, PUT CURSOR AT TOP LEFT CORNER THEN PRINT RESULTS
- PAGE
- CALL CLS ;Call the clear screen routine
- MOV DX,0 ;DH=0, DL=0 (DH=Row,DL=Column)
- MOV BH,0 ;Screen # to use
- ;Call to BIOS: This is where
- LOCATE ;the computer will do the locate
-
-
- CRT: MOV WORD PTR [VARIABLE_1],'XA' ;START VALUE PROCESS
- MOV AX,WORD PTR [STORE_AX] ;MOVE ACCUM VALUE BACK INTO AX
- CALL PROCESS_1 ;PRINT THE CONTENTS OF AX
-
- SUBTTL RESTORE THE ENTRY CONDITIONS, RETURN TO DOS
- PAGE
- ; For the RETURN to execute properly, the stack
- ; must be restored to the point where only the
- ; return parameters are still on the stack.
- ; Any values saved on the stack must be popped
- ; off to restore segregs to the value expected
- ; by DOS.
- ;
- RET ;Far return to DOS
- ;
- ; This changes the CS to point to the Program Segment Prefix
- ; area, whose address was originally passed in DS.
- ; The IP is set to zero. At offset of zero in the
- ; Program Header is an INT 20H instruction which
- ; returns control to DOS.
- ;
- ; RETURN TO DOS CONTROL BY POPPING 2 WORD CS:IP ADDRESS FROM STACK
- ; THAT IS ACTUALLY THE DOS INT 20 LEFT AT THE TOP OF PROGRAM PREFIX
- ; AREA - DS LOCATION CODE START
-
- MAIN ENDP
-
-
- SUBTTL COMMON CODE LOCAL SUBROUTINE, CLEARS SCREEN
- PAGE
- ; This routine is called several times throughout the program.
- ; It uses the BIOS call to do a scroll. To do this, AH must be
- ; 6 (Routine number), AL must be zero (Zero signifies to clear
- ; the window), CX must point to the upper left corner of the
- ; window, (here we use 0,0), and DX must point to the lower
- ; right corner (we use 24,79). Also, BH must be the attribute to
- ; use in the clear screen. We will use 7, the normal attribute.
- ;
- CLS PROC NEAR
- MOV CX,0 ;Upper left coord (0,0)
- MOV DX,2479H ;Bottom right position
- MOV BH,7 ;Normal attribute for CLS
- SCROLL ;Clear entire screen
- RET ;Return to caller
- CLS ENDP
-
-
- PROCESS_1 PROC NEAR
- MOV BYTE PTR [STORE_AL],AL ;STORE LOW BYTE OF ACCUMULATOR
- MOV BYTE PTR [STORE_AH],AH ;DITTO FOR HI BYTE
- CALL HEXDEC ;CONVERT ACCUMULATOR VALUE TO ASCII
- CALL MOVE_TO_VARIABLES ;MOVE ASCII TO STRINGS
- XOR AX,AX ;CLEAR AX REGISTER
- CALL SEND_REPORT ;PRINT ACCUMULATOR CONTENTS
- RET ;RETURN TO CRT CALLER
- PROCESS_1 ENDP
-
- MOVE_TO_VARIABLES PROC NEAR
- MOV AL,BYTE PTR [LOW_NIBBLE_AL] ;LOW NIBBLE OF AL TO AL
- MOV BYTE PTR [VARIABLE_5],AL ;AL TO LOWNIB POS IN STRING
- MOV AL,BYTE PTR [HI_NIBBLE_AL] ;HI NIBBLE OF AL TO AL
- MOV BYTE PTR [VARIABLE_4],AL ;AL TO HINIB POS IN STRING
- MOV AL,BYTE PTR [LOW_NIBBLE_AH] ;LOW NIBBLE OF AH TO AL
- MOV BYTE PTR [VARIABLE_3],AL ;AL TO LOWNIB FOR AH POS
- MOV AL,BYTE PTR [HI_NIBBLE_AH] ;HI NIBBLE OF AH TO AL
- MOV BYTE PTR [VARIABLE_2],AL ;AL TO HINIB FOR AH POS
- RET ;AND RETURN TO CALLER
- MOVE_TO_VARIABLES ENDP
-
- HEXDEC PROC NEAR
- XOR AX,AX ;CLEAR AX REG
- MOV AL,BYTE PTR [STORE_AL] ;GET VALUE
- AND AL,ZEROEFF ;MASK OFF HI NIBBLE
- CALL PROC_LOW_NIBBLE ;AND GET THE ASCII FOR IT
- MOV BYTE PTR [LOW_NIBBLE_AL],AL ;THEN MOVE THAT TO STORAGE
- XOR AX,AX ;CLEAR THE AX REG
- MOV AL,BYTE PTR [STORE_AL] ;GET THE VALUE AGAIN
- CALL PROC_HI_NIBBLE ;TO PROCESS THE HIGH NIBBLE
- CALL PROC_LOW_NIBBLE ;THEN TO THE SAME JOB AGAIN
- MOV BYTE PTR [HI_NIBBLE_AL],AL ;MOVE IT TO STORAGE
- XOR AX,AX ;CLEAR THE AX REGISTER AGAIN
- MOV AL,BYTE PTR [STORE_AH] ;MOVE THE AH REG VALUE INTO AL
- AND AL,ZEROEFF ;AND MASK OFF THE HI NIBBLE
- CALL PROC_LOW_NIBBLE ;AND GET THE ASCII VALUE OF IT
- MOV BYTE PTR [LOW_NIBBLE_AH],AL ;THEN STORE IT
- XOR AX,AX ;CLEAR THE AX REGISTER AGAIN
- MOV AL,BYTE PTR [STORE_AH] ;AND GET THE AH REG VALUE AGAIN
- CALL PROC_HI_NIBBLE ;PROCESS FOR THE HI NIBBLE
- CALL PROC_LOW_NIBBLE ;TO THE SAME JOB AGAIN
- MOV BYTE PTR [HI_NIBBLE_AH],AL ;AND STORE IT
- XOR AX,AX ;CLEAR AX AGAIN
- RET ;AND RETURN TO CALLER
- HEXDEC ENDP
-
- PROC_LOW_NIBBLE PROC NEAR
- DAA ;IF >9 THEN ADD 06
- PUSH AX ;WHICH SET AUX_CARRY_FLAG
- LAHF ;SO LOAD THE FLAGS TO CHECK
- AND AH,10 ;MASK ALL EXCEPT AUX_FLAG
- CMP AH,10 ;CHECK FOR FLAG SET
- JNZ OVER1 ;IF IT ISN'T SET JUST ADD 30H
- POP AX ;RESTORE THE SAVED DATA
- ADD AL,31 ;ELSE IT'S SET, ADD 31 [ >9 ]
- JMP OVER2 ;DON'T ADD AGAIN, JUMP OVER IT
- OVER1: POP AX ;ADDING 30H IS FOR NUMBERS
- ADD AL,30 ;ADDING 31H IS FOR A through F
- OVER2: RET ;RETURN TO CALLER
- PROC_LOW_NIBBLE ENDP
-
- PROC_HI_NIBBLE PROC NEAR
- XOR CX,CX ;CLEAR CX, JUST TO BE SURE
- AND AL,EFFZERO ;MASK OFF LEAST SIGNIFICANT NIBB
- MOV CL,04 ;HOW MANY TIMES TO SHIFT?
- SHR AL,CL ;THEN MOVE MOST SN TO LEAST SN
- RET ;RETURN TO CALLER
- PROC_HI_NIBBLE ENDP
-
- SEND_REPORT PROC NEAR
- MOV SI,OFFSET REPORT_1 ;POINT TO STRING
- XOR CX,CX ;CLEAR CX, JUST TO BE SURE
- MOV CL,3DH ;HOW MANY CHARACTERS TO SEND
- NEXT: LODSB ;LOAD INTO AL POINTED BY SI
- MOV AH,0EH ;MOVE VIDEO FUNCTION INTO AH
- MOV BH,00 ;WRITE TTY TO PAGE ZERO(0)
- INT 10 ;DO IT
- LOOP NEXT ;LOOP IS, CX=CX-1 TILL CX=0000
- RET ;WHEN CX=0000, RETURN
- SEND_REPORT ENDP
-
-
- CODESEG ENDS
-
- END MAIN
- ;LOOP IS, CX=CX-1 TILL CX=00